#include "Photo.h"
#include <string>

SDL_Surface* Photo::mpPhotoBorderSurface = NULL;
SDL_Surface* Photo::mpLastPhotoBorderSurface = NULL;

Photo::Photo()
{
  // TODO: this comes from the example in the SDL docs, but this stuff should be defined for the game and referenced here
  /* Create a 32-bit surface with the bytes of each pixel in R,G,B,A order,
  as expected by OpenGL for textures */
  Uint32 rmask, gmask, bmask, amask;

    /* SDL interprets each pixel as a 32-bit number, so our masks must depend
  on the endianness (byte order) of the machine */
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
  rmask = 0xff000000;
  gmask = 0x00ff0000;
  bmask = 0x0000ff00;
  amask = 0x000000ff;
#else
  rmask = 0x000000ff;
  gmask = 0x0000ff00;
  bmask = 0x00ff0000;
  amask = 0xff000000;
#endif

  mpPhotoSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, PHOTO_SIZE_X, PHOTO_SIZE_Y, 32,
                                 rmask, gmask, bmask, amask);
  if(mpPhotoSurface == NULL) {
    fprintf(stderr, "Photo error: CreateRGBSurface failed: %s\n", SDL_GetError());
    exit(4001);
  }

  // TODO: Fill in the photo surface with pure black pixels (in case photo is 
  // taken offscreen).
  SDL_Rect rc; rc.x = 0; rc.y = 0; rc.w = PHOTO_SIZE_X; rc.h = PHOTO_SIZE_Y;
  SDL_FillRect(mpPhotoSurface, &rc, SDL_MapRGB(mpPhotoSurface->format, 0, 0, 0)); // black

}

void Photo::SetBorder(string imageFilename) {
  // Load up the border image twice. Most photos are show small so we scale the border down to fit.
  // The latest photo is larger and slightly askew so we prepare the border for it in another surface.
  SDL_Surface* pRzSurface=NULL;

  // for most photos
  if (mpPhotoBorderSurface) {
     SDL_FreeSurface(mpPhotoBorderSurface);
     mpPhotoBorderSurface = NULL;
  }
  pRzSurface = IMG_Load(imageFilename.c_str());
  if (pRzSurface) {
    mpPhotoBorderSurface = shrinkSurface(pRzSurface, 2, 2);
    if (!mpPhotoBorderSurface) {
      cerr << "Photo error: can't size " << imageFilename << " for photo border" << endl;
      exit(4007);
    }
    SDL_FreeSurface(pRzSurface);
    pRzSurface = NULL;
  } else {
    cerr << "Photo error: can't load " << imageFilename << " as photo border" << endl;
    exit(4004);
  }

  // now for the latest photo
  if (mpLastPhotoBorderSurface) {
     SDL_FreeSurface(mpLastPhotoBorderSurface);
     mpLastPhotoBorderSurface = NULL;
  }
  pRzSurface= IMG_Load(imageFilename.c_str());
  if (pRzSurface) {
    mpLastPhotoBorderSurface  = rotozoomSurface(pRzSurface, -15.0, 1.0, 0);
    if (!mpLastPhotoBorderSurface) {
      cerr << "Photo error: can't rotate " << imageFilename << " for photo border" << endl;
      exit(4005);
    }
    SDL_FreeSurface(pRzSurface);
    pRzSurface = NULL;
  } else {
    cerr << "Photo error: can't load " << imageFilename << " as photo border" << endl;
    exit(4006);
  }
}

// has to be called before exit to free resources
void Photo::ClearBorder() {
  if (mpPhotoBorderSurface) {
     SDL_FreeSurface(mpPhotoBorderSurface);
     mpPhotoBorderSurface = NULL;
  }
  if (mpLastPhotoBorderSurface) {
     SDL_FreeSurface(mpLastPhotoBorderSurface);
     mpLastPhotoBorderSurface = NULL;
  }
}

int Photo::Shoot(SDL_Surface *src, int x, int y) {
  int nResult = 0;
  if (!src) {
    cerr << "Photo error: invalid destination surface" << endl;
    exit(4002);
  }
  if (!mpPhotoSurface) {
    cerr << "Photo error: Photo not initialized" << endl;
    exit(4003);
  }
  SDL_Rect srcRect;
  srcRect.x = x;
  srcRect.y = y;
  srcRect.w = PHOTO_SIZE_X;
  srcRect.h = PHOTO_SIZE_Y;
  nResult = SDL_BlitSurface(src, &srcRect, mpPhotoSurface, NULL);
  return nResult;
}

int Photo::Draw(SDL_Surface *dst, int x, int y, bool big) {
  int nResult = 0;
  SDL_Surface *pRzSurface = NULL;
  if (!dst)
    cerr << "Photo error: invalid destination surface" << endl;
  if (!mpPhotoSurface)
    cerr << "Photo error: Photo not initialized" << endl;
  if (!big) {
    pRzSurface = shrinkSurface(mpPhotoSurface, 2, 2);
    if (pRzSurface) {
      SDL_Rect dstRect;
      dstRect.x = x;
      dstRect.y = y;
      dstRect.w = PHOTO_SIZE_X / 2; // ignored by blit
      dstRect.h = PHOTO_SIZE_Y / 2; // ignored by blit
      nResult = SDL_BlitSurface(pRzSurface, NULL, dst, &dstRect);
      if (!nResult && mpPhotoBorderSurface) {
        nResult = SDL_BlitSurface(mpPhotoBorderSurface, NULL, dst, &dstRect);
      }
      SDL_FreeSurface(pRzSurface);
      pRzSurface = NULL;
    } else {
      cerr << "Photo error: Shrink failed." << endl;
    }    
    return nResult;
  } else {
    // big is used for the latest photo
    pRzSurface = rotozoomSurface(mpPhotoSurface, -15.0, 1.0, 0);
    if (pRzSurface) {
      SDL_Rect dstRect;
      dstRect.x = x;
      dstRect.y = y;
      dstRect.w = PHOTO_SIZE_X; // ignored by blit
      dstRect.h = PHOTO_SIZE_Y; // ignored by blit
      nResult = SDL_BlitSurface(pRzSurface, NULL, dst, &dstRect);
      if (!nResult && mpLastPhotoBorderSurface) {
        nResult = SDL_BlitSurface(mpLastPhotoBorderSurface, NULL, dst, &dstRect);
      }
      SDL_FreeSurface(pRzSurface);
      pRzSurface = NULL;
    } else {
      cerr << "Photo error: Rotozoom failed." << endl;
    }
    return nResult;
  }
}

Photo::~Photo() {
  if (mpPhotoSurface) {
    SDL_FreeSurface(mpPhotoSurface);
    mpPhotoSurface = NULL;
  }
}
